#include "scene.h"
#include "camera.h"
#include "entity.h"

IMPLEMENT_SINGLETON(c_scene)

c_scene::c_scene()
: m_active_camera(camera_ptr())
{
    create_root(); 
}

c_scene::~c_scene()
{
}

void c_scene::create_root()
{
    m_root_node = scene_node_ptr(new c_scene_node(this, std::string("root")));
}

camera_ptr c_scene::create_camera(const std::string& name, const c_vector3& position, const c_vector3& lookat, const c_vector3& up, const frustum_ptr& frustum)
{
    camera_ptr new_cam(new c_camera(this, name, position, lookat, up, frustum)); 
    BOOST_ASSERT(new_cam);
    
    add_camera(new_cam);

    m_active_camera = new_cam; 
    
    return new_cam;
}


mesh_entity_ptr c_scene::create_entity(const std::string& name, mesh_ptr& mesh_ptr)
{
    mesh_entity_ptr new_entity(new c_mesh_entity(this, name, mesh_ptr)); 
    BOOST_ASSERT(new_entity);
    
    add_scene_node(new_entity); 
    
    return new_entity; 
}

void c_scene::add_scene_node(const scene_node_ptr& node)
{
    BOOST_ASSERT(node); 
    m_root_node->add_child_node(node);
}

void c_scene::add_camera(const camera_ptr& camera)
{
    BOOST_ASSERT(camera);
    m_camera_nodes.push_back(camera);
    m_root_node->add_child_node(camera);
}

void c_scene::update_scene(float dt)
{
    m_root_node->update(this, dt);
}

void c_scene::render_scene()
{
    // 1: frustum culling 

    // 2: sorting and group

    // 3: render
    
    m_root_node->render(this); 
    
}
